import { PrismaClient } from '@prisma/client';
import { createModuleLogger } from '@/utils/logger';

const logger = createModuleLogger('monitored-token-service');

export interface MonitoredTokenData {
  symbol: string;
  name: string;
  coingeckoId: string;
  marketCapRank?: number;
  marketCap?: number;
  currentPrice?: number;
  priceChange24h?: number;
  volume24h?: number;
  isActive?: boolean;
  minValueUsd?: number;
}

export class MonitoredTokenService {
  private static instance: MonitoredTokenService;
  private prisma: PrismaClient;

  private constructor() {
    this.prisma = new PrismaClient();
  }

  public static getInstance(): MonitoredTokenService {
    if (!MonitoredTokenService.instance) {
      MonitoredTokenService.instance = new MonitoredTokenService();
    }
    return MonitoredTokenService.instance;
  }

  // 获取所有活跃的监控代币
  public async getActiveTokens(): Promise<any[]> {
    try {
      return await this.prisma.monitoredToken.findMany({
        where: { isActive: true },
        orderBy: { marketCapRank: 'asc' }
      });
    } catch (error) {
      logger.error('获取活跃代币失败:', error);
      return [];
    }
  }

  // 获取所有代币符号
  public async getActiveTokenSymbols(): Promise<string[]> {
    try {
      const tokens = await this.prisma.monitoredToken.findMany({
        where: { isActive: true },
        select: { symbol: true }
      });
      return tokens.map(token => token.symbol);
    } catch (error) {
      logger.error('获取代币符号失败:', error);
      return [];
    }
  }

  // 检查代币是否在监控列表中
  public async isTokenMonitored(symbol: string): Promise<boolean> {
    try {
      const token = await this.prisma.monitoredToken.findFirst({
        where: { 
          symbol: symbol.toUpperCase(),
          isActive: true 
        }
      });
      return !!token;
    } catch (error) {
      logger.error(`检查代币${symbol}监控状态失败:`, error);
      return false;
    }
  }

  // 获取代币的最小监控金额
  public async getTokenMinValue(symbol: string): Promise<number> {
    try {
      const token = await this.prisma.monitoredToken.findFirst({
        where: { 
          symbol: symbol.toUpperCase(),
          isActive: true 
        },
        select: { minValueUsd: true }
      });
      return token ? Number(token.minValueUsd) : 10000; // 默认 $10,000
    } catch (error) {
      logger.error(`获取代币${symbol}最小监控金额失败:`, error);
      return 10000;
    }
  }

  // 批量插入或更新代币
  public async upsertTokens(tokens: MonitoredTokenData[]): Promise<number> {
    let successCount = 0;
    
    for (const tokenData of tokens) {
      try {
        await this.prisma.monitoredToken.upsert({
          where: { symbol: tokenData.symbol.toUpperCase() },
          update: {
            name: tokenData.name,
            coingeckoId: tokenData.coingeckoId,
            marketCapRank: tokenData.marketCapRank,
            marketCap: tokenData.marketCap ? Math.round(tokenData.marketCap) : null,
            currentPrice: tokenData.currentPrice,
            priceChange24h: tokenData.priceChange24h,
            volume24h: tokenData.volume24h ? Math.round(tokenData.volume24h) : null,
            lastPriceUpdate: new Date(),
            updatedAt: new Date()
          },
          create: {
            symbol: tokenData.symbol.toUpperCase(),
            name: tokenData.name,
            coingeckoId: tokenData.coingeckoId,
            marketCapRank: tokenData.marketCapRank,
            marketCap: tokenData.marketCap ? Math.round(tokenData.marketCap) : null,
            currentPrice: tokenData.currentPrice,
            priceChange24h: tokenData.priceChange24h,
            volume24h: tokenData.volume24h ? Math.round(tokenData.volume24h) : null,
            isActive: tokenData.isActive !== false, // 默认为true
            minValueUsd: tokenData.minValueUsd || 10000,
            lastPriceUpdate: new Date()
          }
        });
        successCount++;
      } catch (error) {
        logger.error(`插入/更新代币 ${tokenData.symbol} 失败:`, error);
      }
    }

    logger.info(`批量操作完成: 成功处理 ${successCount}/${tokens.length} 个代币`);
    return successCount;
  }

  // 更新代币价格
  public async updateTokenPrice(symbol: string, price: number): Promise<void> {
    try {
      await this.prisma.monitoredToken.updateMany({
        where: { 
          symbol: symbol.toUpperCase(),
          isActive: true 
        },
        data: {
          currentPrice: price,
          lastPriceUpdate: new Date()
        }
      });
    } catch (error) {
      logger.error(`更新代币${symbol}价格失败:`, error);
    }
  }

  // 获取代币价格（从数据库）
  public async getTokenPrice(symbol: string): Promise<number> {
    const upperSymbol = symbol.toUpperCase();
    
    try {
      // 稳定币固定价格
      const stablecoins = ['USDT', 'USDC', 'DAI', 'BUSD', 'TUSD', 'FRAX', 'LUSD'];
      if (stablecoins.includes(upperSymbol)) {
        return 1.0;
      }

      // 包装代币映射
      const wrappedTokenMappings: Record<string, string> = {
        'WETH': 'ETH',
        'WBTC': 'BTC',
        'WBNB': 'BNB',
        'WMATIC': 'MATIC',
        'WAVAX': 'AVAX',
        'WFTM': 'FTM'
      };

      const targetSymbol = wrappedTokenMappings[upperSymbol] || upperSymbol;
      
      // 从数据库获取价格
      const token = await this.prisma.monitoredToken.findFirst({
        where: { 
          symbol: targetSymbol,
          isActive: true 
        },
        select: { 
          currentPrice: true, 
          lastPriceUpdate: true,
          symbol: true
        }
      });

      if (!token) {
        logger.debug(`代币 ${symbol} 不在监控列表中`);
        return 0;
      }

      if (!token.currentPrice || Number(token.currentPrice) <= 0) {
        logger.warn(`代币 ${symbol} 价格为空或无效: ${token.currentPrice}`);
        return 0;
      }

      const price = Number(token.currentPrice);
      
      // 检查价格更新时间
      if (token.lastPriceUpdate) {
        const hoursSinceUpdate = (Date.now() - token.lastPriceUpdate.getTime()) / (1000 * 60 * 60);
        if (hoursSinceUpdate > 2) { // 超过2小时未更新
          logger.warn(`代币 ${symbol} 价格已过期 ${hoursSinceUpdate.toFixed(1)} 小时`);
        }
      }
      
      logger.debug(`📊 从数据库获取 ${symbol} 价格: $${price} ${targetSymbol !== upperSymbol ? `(映射到${targetSymbol})` : ''}`);
      return price;
      
    } catch (error) {
      logger.error(`获取代币${symbol}价格失败:`, error);
      return 0;
    }
  }

  // 批量更新代币价格
  public async updateTokenPrices(priceUpdates: Array<{symbol: string, price: number}>): Promise<number> {
    let successCount = 0;
    
    for (const update of priceUpdates) {
      try {
        await this.updateTokenPrice(update.symbol, update.price);
        successCount++;
      } catch (error) {
        logger.error(`批量更新代币${update.symbol}价格失败:`, error);
      }
    }
    
    logger.info(`批量价格更新完成: ${successCount}/${priceUpdates.length} 个代币`);
    return successCount;
  }

  // 获取需要更新价格的代币列表
  public async getTokensNeedingPriceUpdate(maxAgeHours: number = 1): Promise<Array<{symbol: string, coingeckoId: string}>> {
    try {
      const cutoffTime = new Date(Date.now() - maxAgeHours * 60 * 60 * 1000);
      
      const tokens = await this.prisma.monitoredToken.findMany({
        where: {
          isActive: true,
          OR: [
            { lastPriceUpdate: null },
            { lastPriceUpdate: { lt: cutoffTime } },
            { currentPrice: null },
            { currentPrice: { lte: 0 } }
          ]
        },
        select: {
          symbol: true,
          coingeckoId: true,
          lastPriceUpdate: true
        },
        orderBy: { marketCapRank: 'asc' }
      });
      
      logger.info(`发现 ${tokens.length} 个代币需要价格更新`);
      return tokens;
      
    } catch (error) {
      logger.error('获取需要价格更新的代币失败:', error);
      return [];
    }
  }

  // 获取统计信息
  public async getStats(): Promise<{
    totalTokens: number;
    activeTokens: number;
    lastUpdate: Date | null;
  }> {
    try {
      const [total, active, lastUpdate] = await Promise.all([
        this.prisma.monitoredToken.count(),
        this.prisma.monitoredToken.count({ where: { isActive: true } }),
        this.prisma.monitoredToken.findFirst({
          orderBy: { updatedAt: 'desc' },
          select: { updatedAt: true }
        })
      ]);

      return {
        totalTokens: total,
        activeTokens: active,
        lastUpdate: lastUpdate?.updatedAt || null
      };
    } catch (error) {
      logger.error('获取统计信息失败:', error);
      return {
        totalTokens: 0,
        activeTokens: 0,
        lastUpdate: null
      };
    }
  }

  // 获取代币详情
  public async getTokenBySymbol(symbol: string): Promise<any | null> {
    try {
      return await this.prisma.monitoredToken.findFirst({
        where: { symbol: symbol.toUpperCase() }
      });
    } catch (error) {
      logger.error(`获取代币${symbol}详情失败:`, error);
      return null;
    }
  }

  // 启用/禁用代币监控
  public async setTokenActive(symbol: string, isActive: boolean): Promise<boolean> {
    try {
      await this.prisma.monitoredToken.updateMany({
        where: { symbol: symbol.toUpperCase() },
        data: { isActive }
      });
      logger.info(`代币 ${symbol} 监控状态已更新为: ${isActive ? '启用' : '禁用'}`);
      return true;
    } catch (error) {
      logger.error(`更新代币${symbol}监控状态失败:`, error);
      return false;
    }
  }

  // 清理连接
  public async disconnect(): Promise<void> {
    await this.prisma.$disconnect();
  }
} 